<template>
  <div class="editor-part-container">
    <template v-if="loading">
      <div class="editor-spin-container">
        <a-spin tip="Loading..."></a-spin>
      </div>
    </template>
    <template v-else>
      <div class="editor-title-container">
        <a-input v-model:value="formData.title" style="font-size: 30px" :bordered="false"></a-input>
      </div>
      <div class="editor-write-container">
        <Editor class="editor-com-container" ref="editor" v-model:value="formData.content_md" :locale="zhHans"
          :plugins="plugins" @change="handleNoteContent" @paste="handleNotePaste" :upload-images="handleNoteUpload" />
      </div>
    </template>
  </div>
</template>

<script setup>
import _ from 'lodash-es';
// 导入编辑器组件
import { Editor } from '@bytemd/vue-next';
import gfm from '@bytemd/plugin-gfm';
import gemoji from '@bytemd/plugin-gemoji';
// 高亮插件
import highlight from '@bytemd/plugin-highlight';
import frontmatter from '@bytemd/plugin-frontmatter';
import mediumZoom from '@bytemd/plugin-medium-zoom';
import breaks from '@bytemd/plugin-breaks';
// 汉化
import zhHans from 'bytemd/lib/locales/zh_Hans.json';

// 文章接口
import { noteList, updateNote } from '@/apis/note';
import { uploadCosFile } from '@/apis/upload';
import { STATUS_KEY } from '@/contants';


// 导入编辑器样式
import 'bytemd/dist/index.css';
// 代码高亮
import 'highlight.js/styles/vs.css';
// 掘金主题
import 'juejin-markdown-themes/dist/juejin.min.css';


// 接受props
const props = defineProps({
  node: {
    type: Object,
    default: () => ({})
  },
  noteBookNode: {
    type: Object,
    default: () => ({})
  }
});

// 编辑器ref
const editor = ref(null);
// 页面加载
const loading = ref(false);
// 文章数据
const formData = reactive({
  title: '',
  content_md: '',
});

// 插件配置
const plugins = ref([]);

const { $message } = useNuxtApp();

// 重置数据
const handleResetData = item => {
  for (const key in item) {
    formData[key] = item?.[key];
  }
}


// 更新状态
const handleNotePush = async () => {
  const { data } = await updateNote({
    body: {
      noteId: formData?.id,
      title: formData?.title,
      content_md: formData?.content_md,
      state: formData?.state === 1 ? 2 : 3
    },
  });

  if (data.success) {
    $message.success(data.msg);
    initLoadNote();
  }
  else {
    $message.error(data.msg);
  }
}

//改变文章状态
const changeNoteState = node => {
  const basePlugins = [gfm(), gemoji(), highlight(), frontmatter(), mediumZoom(), breaks()];
  plugins.value = [
    ...basePlugins,
    {
      actions: [
        {
          title: STATUS_KEY?.[node?.state],
          icon: STATUS_KEY?.[node?.state],
          position: 'right',
          handler: {
            type: 'action',
            click: () => handleNotePush(),
          },
        },
      ],
    }
  ]
}

// 初始化数据
const initLoadNote = async () => {
  loading.value = true;
  const { data } = await noteList({
    query: {
      pageNo: 1,
      pageSize: 10
    }
  }).finally(() => loading.value = false);

  // 判断获取数据是否成功
  if (data?.success) {
    const { node, noteBookNode } = props;
    // 标题
    const title = node?.value?.title || '';
    // 用户id
    const uid = noteBookNode?.value?.uid || 0;
    // 查找文章
    const note = _.find(data?.data, item => item.title === title && item.uid === uid);
    // 重置内容
    handleResetData(note ? note : { title: '', content_md: '' });
    // 改变文章状态
    note && changeNoteState(note);
  }
}

// 文章内容
const handleNoteContent = value => {
  if (value) {
    // 获取文章内容 去除内容标签
    const content = value.replace(/<[^>]*>/g, '');
    formData.content_md = content;
  }
}

// 文本复制
const handleNotePaste = async event => {
  // 获取 'html' 格式的数据,数据是一个字符串，而不是实际的DOM元素
  const htmlData = event.clipboardData.getData('text/html');
  // 转成DOM元素
  const parser = new DOMParser();
  const doc = parser.parseFromString(htmlData, "text/html");

  // 由于粘贴的是第三方内容，图片需要处理一下
  const images = doc.getElementsByTagName("img");

  if (images.length) {
    const tasks = [];
    // 你是否会觉得下面的代码为啥要用images[i]而不用item？ 因为此处的images[i] != item
    Array.from(images).forEach((item, i) => {
      // 如果图片不是可信赖的（自己公司的）
      if (!images[i].src.includes("https://img.xxx.com")) {
        tasks.push({});
      }
    });
    await Promise.all(tasks);
  }
  // 转回html字符串传给后端
  let serializer = new XMLSerializer();
  let str = "";
  for (let node of doc.body.childNodes) {
    str += serializer.serializeToString(node);
  }
}


// 上传图片
const handleNoteUpload = async files => {
  return Promise.all(
    files.map(async (file) => {
      const formData = new FormData();
      formData.append('file', file);

      const { data } = await uploadCosFile({
        body: formData
      });

      return {
        url: data.url
      }
    })
  );
}

// 监听node节点的变化
watch(props.node, () => initLoadNote());
</script>

<style lang="less" scoped>
.editor-part-container {
  display: flex;
  flex-direction: column;
  width: 100%;
  min-width: 100%;
  height: 100%;

  .editor-spin-container {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .editor-title-container {
    width: 100%;
    height: 70px;
    line-height: 70px;
  }

  .editor-write-container {
    width: 100%;
    height: calc(100% - 70px);

    .editor-com-container {
      width: 100%;
      height: 100%;
    }

    :deep(.bytemd) {
      height: 100% !important;
    }

    :deep(.markdown-body) {
      * {
        padding: 0;
        margin: 0;
      }
    }

  }
}
</style>